---
type: tutorial
title: '마른 땅으로 돌아갑니다. 섬이 필요 없이 낮부터 밤까지 블로그를 운영하세요!'
description: |-
  튜토리얼: 첫 번째 Astro 블로그 구축 — JavaScript 및 CSS만 사용하여 밝은/어두운 테마 토글 구축
i18nReady: true
---

import Box from '~/components/tutorial/Box.astro';
import Checklist from '~/components/Checklist.astro';
import MultipleChoice from '~/components/tutorial/MultipleChoice.astro';
import Option from '~/components/tutorial/Option.astro';
import PreCheck from '~/components/tutorial/PreCheck.astro';
import { Steps } from '@astrojs/starlight/components';

이제 대화형 요소를 위한 Astro 섬을 구축할 수 있으므로 바닐라 JavaScript와 CSS만으로 꽤 많은 작업을 수행할 수 있다는 사실을 잊지 마세요!

브라우저에 프레임워크 JavaScript를 전송하지 않고 상호작용을 위해 또 다른 `<script>` 태그를 사용하여 사용자가 밝은 테마와 어두운 테마 사이를 전환할 수 있도록 클릭 가능한 아이콘을 만들어 보겠습니다.

<PreCheck>
  - JavaScript 및 CSS만으로 대화형 테마 토글 구축
  - 가능한 한 브라우저에 JavaScript를 적게 보내기!
</PreCheck>

## 테마 토글 아이콘 추가 및 스타일 지정

<Steps>
1. `src/components/ThemeIcon.astro`에 새 파일을 만들고 다음 코드를 붙여넣습니다.

    ```astro title="src/components/ThemeIcon.astro"
    ---
    ---
    <button id="themeToggle" aria-label="Toggle theme">
      <svg aria-hidden="true" width="30px" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
        <path class="sun" fill-rule="evenodd" d="M12 17.5a5.5 5.5 0 1 0 0-11 5.5 5.5 0 0 0 0 11zm0 1.5a7 7 0 1 0 0-14 7 7 0 0 0 0 14zm12-7a.8.8 0 0 1-.8.8h-2.4a.8.8 0 0 1 0-1.6h2.4a.8.8 0 0 1 .8.8zM4 12a.8.8 0 0 1-.8.8H.8a.8.8 0 0 1 0-1.6h2.5a.8.8 0 0 1 .8.8zm16.5-8.5a.8.8 0 0 1 0 1l-1.8 1.8a.8.8 0 0 1-1-1l1.7-1.8a.8.8 0 0 1 1 0zM6.3 17.7a.8.8 0 0 1 0 1l-1.7 1.8a.8.8 0 1 1-1-1l1.7-1.8a.8.8 0 0 1 1 0zM12 0a.8.8 0 0 1 .8.8v2.5a.8.8 0 0 1-1.6 0V.8A.8.8 0 0 1 12 0zm0 20a.8.8 0 0 1 .8.8v2.4a.8.8 0 0 1-1.6 0v-2.4a.8.8 0 0 1 .8-.8zM3.5 3.5a.8.8 0 0 1 1 0l1.8 1.8a.8.8 0 1 1-1 1L3.5 4.6a.8.8 0 0 1 0-1zm14.2 14.2a.8.8 0 0 1 1 0l1.8 1.7a.8.8 0 0 1-1 1l-1.8-1.7a.8.8 0 0 1 0-1z"/>
        <path class="moon" fill-rule="evenodd" d="M16.5 6A10.5 10.5 0 0 1 4.7 16.4 8.5 8.5 0 1 0 16.4 4.7l.1 1.3zm-1.7-2a9 9 0 0 1 .2 2 9 9 0 0 1-11 8.8 9.4 9.4 0 0 1-.8-.3c-.4 0-.8.3-.7.7a10 10 0 0 0 .3.8 10 10 0 0 0 9.2 6 10 10 0 0 0 4-19.2 9.7 9.7 0 0 0-.9-.3c-.3-.1-.7.3-.6.7a9 9 0 0 1 .3.8z"/>
      </svg>
    </button>

    <style>
      #themeToggle {
        border: 0;
        background: none;
      }
      .sun { fill: black; }
      .moon { fill: transparent; }
      
      :global(.dark) .sun { fill: transparent; }
      :global(.dark) .moon { fill: white; }
    </style>
    ```

2. `Header.astro`에 `<ThemeIcon />` 컴포넌트를 가져와 추가하여 모든 페이지에 표시되도록 합니다. `<ThemeIcon />`과 `<Menu />`를 `<div>`로 감싸 스타일링을 위해 그룹화하고, 레이아웃 개선을 위한 기본 스타일을 적용하기 위해 아래와 같이 `<style>` 태그를 추가합니다.

    ```astro title="src/components/Header.astro" ins={4,8-9,11,16-21}
    ---
    import Menu from './Menu.astro';
    import Navigation from './Navigation.astro';
    import ThemeIcon from './ThemeIcon.astro';
    ---
    <header>
      <nav>
        <div>
          <ThemeIcon />
          <Menu />
        </div>
        <Navigation />
      </nav>
    </header>
    
    <style>
      div {
        display: flex;
        justify-content: space-between;
      }
    </style>
    ```

3. `http://localhost:4321`에서 브라우저 미리보기를 방문하여 이제 모든 페이지에서 아이콘을 확인하세요. 클릭해 볼 수는 있지만 아직 대화형으로 만드는 스크립트를 작성하지 않았습니다.
</Steps>

## 어두운 테마에 CSS 스타일 추가

어두운 테마에서 사용할 대체 색상을 선택하세요.

<Steps>
1. `global.css`에서 몇 가지 어두운 스타일을 정의합니다. 직접 선택하거나 복사하여 붙여넣을 수 있습니다.

    ```css title="src/styles/global.css"
    html.dark {
      background-color: #0d0950;
      color: #fff;
    }
    
    .dark .menu {
      background-color: #fff;
      color: #000;
    }

    .dark .nav-links a:hover,
    .dark .nav-links a:focus {
      color: #0d0950;
    }

    .dark .nav-links a {
      color: #fff;
    }
    
    .dark a {
      color: #ff9776;
    }
    ```
</Steps>

:::tip[접근성을 위한 색상 확인]
다크모드를 지원하기 위해 사이트를 업데이트할 때, 사용된 일부 색상을 수정해야 할 수도 있습니다.

새로운 스타일과 색상을 추가할 때는 항상 렌더링된 사이트를 확인하고 필요한 경우 조정하세요! 이는 다크 모드에서 다른 스타일을 표시하기 위해 `.dark` CSS 스타일 규칙을 추가하거나, 두 테마 모두에서 동일하게 잘 작동하도록 일부 색상을 업데이트하는 것을 의미할 수 있습니다.

웹사이트 색상 조합을 구성할 때는 대비 검사기 같은 접근성 도구를 활용하는 것을 고려해 보세요. 또는 브라우저 확장 프로그램을 통해 웹사이트를 검사하여 잠재적인 문제를 발견할 수도 있습니다.
:::

## 클라이언트 측 상호작용 추가

Astro 컴포넌트에 상호작용을 추가하려면 `<script>` 태그를 사용할 수 있습니다. 이 스크립트는 `localStorage`에서 현재 테마를 확인 및 설정하고 아이콘을 클릭할 때 테마를 전환할 수 있습니다.

<Steps>
1. `src/components/ThemeIcon.astro`의 `<style>` 태그 뒤에 다음 `<script>` 태그를 추가합니다.

    ```astro title="src/components/ThemeIcon.astro" ins={9-38}
    <style>
      .sun { fill: black; }
      .moon { fill: transparent; }

      :global(.dark) .sun { fill: transparent; }
      :global(.dark) .moon { fill: white; }
    </style>

    <script is:inline>
      const theme = (() => {
        const localStorageTheme = localStorage?.getItem("theme") ?? '';
        if (['dark', 'light'].includes(localStorageTheme)) {
          return localStorageTheme;
        }
        if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
          return 'dark';
        }
          return 'light';
      })();
          
      if (theme === 'light') {
        document.documentElement.classList.remove('dark');
      } else {
        document.documentElement.classList.add('dark');
      }

      window.localStorage.setItem('theme', theme);

      const handleToggleClick = () => {
        const element = document.documentElement;
        element.classList.toggle("dark");
        
        const isDark = element.classList.contains("dark");
        localStorage.setItem("theme", isDark ? "dark" : "light");
      }

      document.getElementById("themeToggle")?.addEventListener("click", handleToggleClick);
    </script>
    ```

2. `http://localhost:4321`에서 브라우저 미리보기를 확인하고 테마 아이콘을 클릭하세요. 밝은 테마와 어두운 테마 간에 변경할 수 있는지 확인하세요.
</Steps>

<Box icon="question-mark">

### 지식 테스트

다음 각 문장이 Astro `<script>` 태그, UI 프레임워크 컴포넌트 또는 둘 다를 설명하는지 선택하세요.

1. 웹사이트에 대화형 UI 요소를 포함할 수 있습니다.

    <MultipleChoice>
      <Option>
        Astro `<script>` 태그
      </Option>
      <Option>
        UI 프레임워크 컴포넌트
      </Option>
      <Option isCorrect>
        둘 다
      </Option>
    </MultipleChoice>

2. JavaScript를 클라이언트에 보내고 브라우저에서 실행하기 위해 `client:`를 포함하지 않는 한 사이트에 정적 요소가 생성됩니다.

    <MultipleChoice>
      <Option>
        Astro `<script>` 태그
      </Option>
      <Option isCorrect>
        UI 프레임워크 컴포넌트
      </Option>
      <Option>
        둘 다
      </Option>
    </MultipleChoice>

3. 이를 통해 해당 기술 스택을 사용하여 완전히 새로운 프로젝트를 시작할 필요 없이 새로운 프레임워크를 "시험해 볼" 수 있습니다.

    <MultipleChoice>
      <Option>
        Astro `<script>` 태그
      </Option>
      <Option isCorrect>
        UI 프레임워크 컴포넌트
      </Option>
      <Option>
        둘 다
      </Option>
    </MultipleChoice>

4. 이를 통해 다른 프레임워크에서 작성한 코드를 재사용할 수 있으며 종종 사이트에 바로 넣을 수 있습니다.

    <MultipleChoice>
      <Option>
        Astro `<script>` 태그
      </Option>
      <Option isCorrect>
        UI 프레임워크 컴포넌트
      </Option>
      <Option>
        둘 다
      </Option>
    </MultipleChoice>

5. 이를 통해 다른 JavaScript 프레임워크를 알거나 배울 필요 없이 대화형 기능을 추가할 수 있습니다.

    <MultipleChoice>
      <Option isCorrect>
        Astro `<script>` 태그
      </Option>
      <Option>
        UI 프레임워크 컴포넌트
      </Option>
      <Option>
        둘 다
      </Option>
    </MultipleChoice>
</Box>

<Box icon="check-list">

## 체크리스트

<Checklist>
- [ ] 프레임워크를 추가하고 싶지 않을 때 상호작용을 위해 JavaScript를 사용할 수 있습니다.
</Checklist>
</Box>

### 추가 자료

- [Astro의 클라이언트 측 `<script>`](/ko/guides/client-side-scripts/)
